Categories
React

Framer Motion — Animation Hooks

Spread the love

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

useReducedMotion

We can use the useReducedMotion hook to animate our elements based on the current device’s reduced motion setting.

For example, we can write:

import React, { useState } from "react";
import { motion, useReducedMotion } from "framer-motion";

export default function App() {
  const shouldReduceMotion = useReducedMotion();
  const closedX = shouldReduceMotion ? 0 : "-100%";
  const [isOpen, setIsOpen] = useState(true);

  return (
    <>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      <motion.div
        animate={{
          opacity: isOpen ? 1 : 0,
          x: isOpen ? 0 : closedX
        }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      />
    </>
  );
}

We call the useReduceMotion hook to get the shouldReduceMotion variable.

We can use that to check if reduced motion setting is enabled.

Then we can use that to position the div based on the shouldReduceMotion value.

usePresence

The usePresence hook lets us access information about whether an element is still present in the React tree.

If isPresent is false , then a component has been remove from the tree, but AnimatePresence won’t remove it until safeToRemove has been called.

For example, we can write:

import React, { useEffect, useState } from "react";
import { usePresence } from "framer-motion";

export const Component = () => {
  const [isPresent, safeToRemove] = usePresence();

  useEffect(() => {
    console.log(isPresent);
    !isPresent && setTimeout(safeToRemove, 1000);
  }, [isPresent]);

  return <div style={{ backgroundColor: "red", width: 100, height: 100 }} />;
};

export default function App() {
  const [isOpen, setIsOpen] = useState(true);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      {isOpen && <Component />}
    </div>
  );
}

to watch the isPresent value in the useEffect callback.

Then we call safeToRemove to remove the component when it’s unloaded.

useIsPresent

The useIsPresent hook is similar to usePresence except that it doesn’t return the safeToRemove function.

For example, we can write:

import React, { useEffect, useState } from "react";
import { useIsPresent } from "framer-motion";

export const Component = () => {
  const isPresent = useIsPresent();

  useEffect(() => {
    isPresent && console.log("is present");
  }, [isPresent]);

  return <div style={{ backgroundColor: "red", width: 100, height: 100 }} />;
};

export default function App() {
  const [isOpen, setIsOpen] = useState(true);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      {isOpen && <Component />}
    </div>
  );
}

to log the isPresent value.

useDragControls

We can use the useDragControls hook to create drag controls.

The drag controls can be passed into the draggable component’s dragControls prop.

It exposes a start method that can start dragging from pointer events or other components.

For instance, we can write:

import { motion, useDragControls } from "framer-motion";
import React from "react";

export default function App() {
  const dragControls = useDragControls();

  function startDrag(event) {
    dragControls.start(event, { snapToCursor: true });
  }

  return (
    <>
      <div onPointerDown={startDrag}>click me</div>
      <motion.div
        style={{ backgroundColor: "red", width: 100, height: 100 }}
        drag="x"
        dragControls={dragControls}
      />
    </>
  );
}

We create the dragControls with the useDragControls hook.

Then we pass that into the dragControls prop.

The drag prop is set to 'x' so that we can drag horizontally.

We also created the startDrag function to call dragControls.start to start dragging.

We pass in the mouse event object into start and set snapToCursor to true to move the div towards our mouse cursor when we click on ‘click me’.

Conclusion

We can use various hooks that come with Framer Motion to control our animation.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *